package com.csh.subject.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.csh.subject.common.entity.PageResult;
import com.csh.subject.common.enums.IsDeletedFlagEnum;
import com.csh.subject.domain.convert.SubjectInfoConvert;
import com.csh.subject.domain.entity.SubjectInfoBo;
import com.csh.subject.domain.entity.SubjectOptionBo;
import com.csh.subject.domain.handler.subject.SubjectTypeHandler;
import com.csh.subject.domain.handler.subject.SubjectTypeHandlerFactory;
import com.csh.subject.domain.service.SubjectInfoDomainService;
import com.csh.subject.infra.basic.entity.SubjectInfo;
import com.csh.subject.infra.basic.entity.SubjectLabel;
import com.csh.subject.infra.basic.entity.SubjectMapping;
import com.csh.subject.infra.basic.service.SubjectInfoService;
import com.csh.subject.infra.basic.service.SubjectLabelService;
import com.csh.subject.infra.basic.service.SubjectMappingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SubjectInfoDomainServiceImpl implements SubjectInfoDomainService {
    @Resource
    private SubjectInfoService subjectInfoService;

    @Resource
    private SubjectTypeHandlerFactory subjectTypeHandlerFactory;

    @Resource
    private SubjectMappingService subjectMappingService;

    @Resource
    private SubjectLabelService subjectLabelService;

    /**
     * 新增题目
     * @param subjectInfoBo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SubjectInfoBo subjectInfoBo) {
        if (log.isInfoEnabled()){
            log.info("SubjectInfoDomainServiceImpl.add.Bo:{}", JSON.toJSONString(subjectInfoBo));
        }

        //先在题目的主表插入基本的数据
        SubjectInfo subjectInfo = SubjectInfoConvert.INSTANCE.convertBoToInfo(subjectInfoBo);
        subjectInfo.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        subjectInfoService.insert(subjectInfo);

        //根据传入的题目类型，工厂对象调用方法后返回的是对应的 “题目类型TypeHandler”
        //然后调用add方法，向对应的题目副表插入数据
        SubjectTypeHandler handler = subjectTypeHandlerFactory.getHandler(subjectInfo.getSubjectType());
        //下面subjectInfo之所以可以拿到id，是因为mapper.xml映射文件里用到了函数，插入数据之后可以拿到这条数据的id
        subjectInfoBo.setId(subjectInfo.getId());
        handler.add(subjectInfoBo);
        //向mapping表里插入数据
        List<Integer> categoryIds = subjectInfoBo.getCategoryIds();
        List<Integer> labelIds = subjectInfoBo.getLabelIds();
        List<SubjectMapping> mappingList = new LinkedList<>();
        categoryIds.forEach(categoryId -> {
            labelIds.forEach(labelId -> {
                SubjectMapping subjectMapping = new SubjectMapping();
                subjectMapping.setSubjectId(subjectInfo.getId());
                subjectMapping.setCategoryId(Long.valueOf(categoryId));
                subjectMapping.setLabelId(Long.valueOf(labelId));
                subjectMapping.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
                mappingList.add(subjectMapping);
            });
        });
        subjectMappingService.batchInsert(mappingList);

    }

    /**
     * 分页查询题目列表？？？  有点问题后面改
     * @param subjectInfoBo
     * @return
     */
    @Override
    public PageResult<SubjectInfoBo> getSubjectPage(SubjectInfoBo subjectInfoBo) {
        PageResult<SubjectInfoBo> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectInfoBo.getPageNo());
        pageResult.setPageSize(subjectInfoBo.getPageSize());
        int start = (subjectInfoBo.getPageNo() - 1) * subjectInfoBo.getPageSize();
        SubjectInfo subjectInfo = SubjectInfoConvert.INSTANCE.convertBoToInfo(subjectInfoBo);
        int count = subjectInfoService.countByCondition(subjectInfo,
                subjectInfoBo.getCategoryId(),subjectInfoBo.getLabelId());
        if (count == 0){
            return pageResult;
        }
        List<SubjectInfo> subjectInfoList = subjectInfoService.queryPage(subjectInfo, subjectInfoBo.getCategoryId()
                , subjectInfoBo.getLabelId(), start, subjectInfoBo.getPageSize());
        List<SubjectInfoBo> subjectInfoBoList = SubjectInfoConvert
                .INSTANCE.convertInfoToBoList(subjectInfoList);
        subjectInfoBoList.forEach(info -> {
            SubjectMapping subjectMapping = new SubjectMapping();
            subjectMapping.setSubjectId(info.getId());
            List<SubjectMapping> mappingList = subjectMappingService.queryLabelId(subjectMapping);
            List<Long> labelIds = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());
            List<SubjectLabel> labelList = subjectLabelService.batchQueryByIds(labelIds);
            List<String> labelNames = labelList.stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());
            info.setLabelName(labelNames);
        });
        pageResult.setRecords(subjectInfoBoList);
        pageResult.setTotal(count);
        return pageResult;
    }

    /**
     * 查询题目详情
     * @param subjectInfoBo
     * @return
     */
    @Override
    public SubjectInfoBo querySubjectInfo(SubjectInfoBo subjectInfoBo) {
        //传过来题目id形参，根据id查题目主表，拿到对应的题目信息
        SubjectInfo subjectInfo = subjectInfoService.queryById(subjectInfoBo.getId());
        //根据题目类型，拿到对应的题目策略实现类
        SubjectTypeHandler handler = subjectTypeHandlerFactory.getHandler(subjectInfo.getSubjectType());
        //调用对应实现类的方法，拿到对应题目的答案或选项
        SubjectOptionBo subjectOptionBo = handler.query(subjectInfo.getId());
        //将 题目主要信息 和 题目答案 都传进去做转换 后面返回给前端
        SubjectInfoBo infoBoResult = SubjectInfoConvert.INSTANCE.convertOptionAndInfoToBo(subjectOptionBo,subjectInfo);

        //操作映射表，现根据题目id查标签id
        SubjectMapping subjectMapping = new SubjectMapping();
        subjectMapping.setSubjectId(subjectInfo.getId());
        subjectMapping.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        List<SubjectMapping> mappingList = subjectMappingService.queryLabelId(subjectMapping);
        List<Long> labelIdList = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());
        //拿到标签ids，就可以查标签名了
        List<SubjectLabel> labelList = subjectLabelService.batchQueryByIds(labelIdList);
        List<String> labelNameList = labelList.stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());

        infoBoResult.setLabelName(labelNameList);
        return infoBoResult;
    }
}
